const { Op } = require('sequelize')
const Mysequelize = require('@/models')
const R = require('@/models/Response')
const {
  Department,
  CooperatDepartment,
  UserDepartment,
  Source,
  User
} = require('@/models/model')
const { ERROR_USER_CODE } = require('@/constants/errorCode')
const { generatId } = require('@/utils/idUtil')
const { sortModel, delModel, listModel } = require('@/utils/controllerCommon')
const { SEPARATE_CHAR } = require('../constants')

Department.belongsTo(Department, { foreignKey: 'pid', as: 'parent' })

/**
 * 列表查询部门接口
 * @param {*} ctx
 * @returns
 */
module.exports.listDep = async (ctx) => {
  const { name, pid } = ctx.query
  const whereCondition = {}
  if (name) {
    whereCondition.name = {
      [Op.like]: `%${name}%`
    }
  }
  if (pid) {
    whereCondition.pid = BigInt(pid)
  }
  const orderCondition = [['sort']]
  await listModel(Department)(
    ctx,
    whereCondition,
    orderCondition,
    {
      include: [
        [
          Mysequelize.literal(
            `CASE WHEN EXISTS (SELECT 1 FROM department as md WHERE md.pid = department.id) THEN 0 ELSE 1 END`
          ),
          'isLeaf'
        ],
        [
          Mysequelize.literal(
            `CASE WHEN EXISTS (SELECT 1 FROM user_department as ud WHERE ud.department_id = department.id) THEN 0 ELSE 1 END`
          ),
          'isUserLeaf'
        ]
      ]
    },
    [
      {
        model: Source,
        required: false,
        where: {
          parentLevel: '-1'
        }
      },
      {
        model: Department,
        as: 'parent'
      },
      {
        model: CooperatDepartment,
        as: 'copDepartments',
        attributes: ['linkDepId']
      }
    ]
  )
}

/**
 * 列表查询部门接口,必须属于当前用户
 * @param {*} ctx
 * @returns
 */
module.exports.listUserDep = async (ctx) => {
  const { name, pid, page, pageSize } = ctx.query

  // 系统管理员不受限制，走上面一个接口
  const user = await User.findByPk(BigInt(ctx.user.id))
  if (user.roleId === '1') {
    await this.listDep(ctx)
    return
  }

  // 这里pid可能有误
  let parentLevel = '-1,1'
  const res = await Department.findByPk(BigInt(pid))
  if (res) {
    parentLevel = res.parentLevel + SEPARATE_CHAR + res.id
  }

  const whereCondition = {}
  if (name) {
    whereCondition.name = {
      [Op.like]: `%${name}%`
    }
  }
  if (pid) {
    whereCondition.parentLevel = {
      [Op.like]: parentLevel + '%'
    }
  }
  const orderCondition = [['sort']]

  let { rows, count } = await Department.findAndCountAll({
    where: whereCondition,
    order: orderCondition,
    attributes: {
      include: [
        [
          Mysequelize.literal(
            `CASE WHEN EXISTS (SELECT 1 FROM department as md WHERE md.pid = department.id) THEN 0 ELSE 1 END`
          ),
          'isLeaf'
        ],
        [
          Mysequelize.literal(
            `CASE WHEN EXISTS (SELECT 1 FROM user_department as ud WHERE ud.department_id = department.id) THEN 0 ELSE 1 END`
          ),
          'isUserLeaf'
        ]
      ]
    },
    include: [
      {
        model: Source,
        required: false,
        where: {
          parentLevel: '-1'
        }
      },
      {
        model: Department,
        as: 'parent'
      },
      {
        model: CooperatDepartment,
        as: 'copDepartments',
        attributes: ['linkDepId']
      },
      {
        model: UserDepartment,
        required: true,
        where: {
          userId: BigInt(ctx.user.id)
        }
      }
    ]
  })

  rows = rows.filter((item) => {
    // 如何证明它是第一层？ 条件：没有其他的parentLevel为它的子集
    // 不存在说明该item的parentLevel不包含任何人，说明它是根
    return !rows.some((v) => {
      // 是否存在一个数据，当前item，startwith其他人，如果startwith了，说明不是根
      return (
        item.parentLevel.startsWith(v.parentLevel) &&
        item.parentLevel !== v.parentLevel
      )
    })
  })

  count = rows.length

  //返回
  ctx.body = R.success({
    page,
    pageSize,
    total: count,
    pages: Math.ceil(count / pageSize),
    items: rows
  })
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 更新部门的协作部门
 * @param {*} cooperatDepIds 协作部门ID数组
 * @param {*} depId 部门ID
 * @param {*} userId 用户ID
 * @param {*} t 事务对象
 */
const updateCooperatDep = async (cooperatDepIds, depId, userId, t) => {
  for (let i = 0; i < cooperatDepIds.length; i++) {
    const cooperatDepId = generatId()
    await CooperatDepartment.create(
      {
        id: cooperatDepId,
        depId,
        linkDepId: cooperatDepIds[i],
        createUser: userId,
        updateUser: userId
      },
      {
        transaction: t
      }
    )
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 创建部门接口
 * @param {*} ctx
 */
module.exports.createDep = async (ctx) => {
  const t = await Mysequelize.transaction()
  const { name, pid, sizeMax, cooperatDepIds, desc } = ctx.request.body

  let parentLevel = '-1'
  if (pid !== '-1') {
    // 找到pid对应部门的pathLevel, 然后加上（',pid'）
    const p = await Department.findByPk(BigInt(pid))
    parentLevel = p.parentLevel + SEPARATE_CHAR + pid
  }

  const nextId = generatId()
  const sort = await Department.max('sort')
  let createObj = {
    id: nextId,
    pid,
    parentLevel,
    name,
    sort: sort + 1,
    sizeMax: sizeMax,
    sizeUse: 0,
    createUser: ctx.user.id,
    updateUser: ctx.user.id
  }
  if (desc) {
    createObj.desc = desc
  }
  try {
    // 到这里可以进行部门的添加了,排序字段默认是最大值
    const mydep = await Department.create(createObj, {
      transaction: t
    })
    // 操作协作部门，[-1],[0] [xxx,111]
    await updateCooperatDep(cooperatDepIds, nextId, ctx.user.id, t)

    // 创建部门的同时创建部门文件夹
    const sourceId = generatId()
    await Source.create(
      {
        id: sourceId,
        targetType: 2,
        targetId: nextId,
        filename: name,
        parentId: '-1',
        isDir: 1,
        fileId: '-1',
        type: 0,
        sizeDesc: '--',
        deleteFlag: 0,
        parentLevel: '-1',
        createUser: ctx.user.id,
        updateUser: ctx.user.id
      },
      {
        transaction: t
      }
    )

    await t.commit()
    ctx.logs = { depId: mydep.id }
    ctx.body = R.success()
  } catch (error) {
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.DEP_CREATE_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 更新部门接口
 * @param {*} ctx
 */
module.exports.updateDep = async (ctx) => {
  const t = await Mysequelize.transaction()
  const { depId, name, pid, sizeMax, cooperatDepIds, desc } = ctx.request.body

  // 走到这里，说明pid正常,更新parentLevel
  // 当前depId对应部门的parentLevel改变，还有其子孙部门也需要修改
  let parentLevel = '-1'
  if (pid !== '-1') {
    // 找到pid对应部门的pathLevel, 然后加上（',pid'）
    const p = await Department.findByPk(BigInt(pid))
    parentLevel = p.parentLevel + SEPARATE_CHAR + pid
  }

  // 至此就得到了depId 新的parentLevel
  // 查询出depId的所有子孙部门
  const subDeps = await Department.findAll({
    where: {
      parentLevel: {
        [Op.like]: `%${depId}%`
      }
    }
  })

  const regex = new RegExp(`${depId}(.*)`)
  const subDepsUpdateObjs = subDeps.map((item) => {
    // 将原先的parentLevel进行处理
    const result = item.parentLevel.match(regex)[0]
    return {
      id: item.id,
      parentLevel: parentLevel + SEPARATE_CHAR + result
    }
  })

  // await Department.bulk

  const updateObj = {
    name,
    pid,
    parentLevel,
    sizeMax
  }
  if (desc) {
    updateObj.desc = desc
  }
  try {
    // 进行子部门parentLevel的更新
    for (let i = 0; i < subDepsUpdateObjs.length; i++) {
      await Department.update(subDepsUpdateObjs[i], {
        where: {
          id: subDepsUpdateObjs[i].id
        },
        transaction: t
      })
    }

    // 进行部门信息的更新
    await Department.update(updateObj, {
      where: {
        id: BigInt(depId)
      },
      transaction: t
    })

    // 将部门对应的根文件夹页更新
    await Source.update(
      {
        filename: name
      },
      {
        where: {
          parentLevel: '-1',
          targetId: BigInt(depId)
        },
        transaction: t
      }
    )

    // 将此部门的协作部门全部删除后，重新设置
    await CooperatDepartment.destroy({
      where: {
        depId: BigInt(depId)
      },
      transaction: t
    })

    await updateCooperatDep(cooperatDepIds, depId, ctx.user.id, t)
    await t.commit()
    ctx.body = R.success()
  } catch (e) {
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.DEP_UPDATE_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 批量设置部门空间大小接口
 * @param {*} ctx
 */
module.exports.setDepsSizeMax = async (ctx) => {
  const t = await Mysequelize.transaction()
  const { depIds, sizeMax } = ctx.request.body
  try {
    // 更新sizeMax
    Department.update(
      {
        sizeMax
      },
      {
        where: {
          id: {
            [Op.in]: depIds.map((item) => BigInt(item))
          }
        }
      }
    )
    await t.commit()
    ctx.body = R.success()
  } catch (error) {
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.DEP_SET_SIZEMAX_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 批量删除部门接口
 * @param {*} ctx
 */
module.exports.delDeps = async (ctx) => {
  await delModel(
    Department,
    ERROR_USER_CODE.DEP_DEL_ERROR,
    'depIds'
  )(ctx, [
    { model: CooperatDepartment, idName: 'depId' },
    { model: CooperatDepartment, idName: 'linkDepId' },
    { model: UserDepartment, idName: 'departmentId' }
  ])

  // TODO：第一种：同时删除system_option表记录的默认部门
  // 第二种：查询system_option的默认部门时，看是否存在那条记录，进行自更新
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 部门排序接口
 * @param {*} ctx
 */
module.exports.sortDeps = async (ctx) => {
  await sortModel(Department, ERROR_USER_CODE.DEP_SORT_ERROR, 'depIds')(ctx)
}
